home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Commun⁄Network / RevRdist Folder / RevRdist / RevRINIT src / RevRINIT.c
Encoding:
C/C++ Source or Header  |  1992-01-14  |  13.2 KB  |  569 lines  |  [TEXT/KAHL]

  1. /*
  2.  * RevRINIT.c - INIT to cause RevRdist to be run at system boot time
  3.  */
  4. #include "RevRdist.h"
  5. #include <asm.h>
  6. #include "volops.h"
  7.  
  8. /*
  9.  * Structure of startup header
  10.  */
  11. struct startp {
  12.     Integer        startid;            /* id word */
  13.     ProcPtr        entryp;                /* boot code entry point */
  14.     Integer        version;            /* startup version */
  15.     Integer        azero;
  16.     Str15        sysname;            /* name of system resource file */
  17.     Str15        shellname;            /* name of system shell */
  18.     Str15        debuggername;        /* name of debugger file */
  19.     Str15        disassmname;        /* name of disassembler file */
  20.     Str15        startscreen;        /* name of startup screen image file */
  21.     Str15        startappl;            /* name of first program to run */
  22.     Str15        scrapname;            /* name of disk scrap file */
  23.     Integer        fcbcnt;                /* number of file control blocks */
  24.     Integer        eventcnt;            /* size of event queue */
  25.     Longint        heapsize1;            /* heap size on 128k system */
  26.     Longint        reserved;
  27.     Longint        heapsize2;            /* heap size on 512k system */
  28. };
  29. typedef struct startp startp_t;
  30. #define STARTID 'LK'                /* correct value of id word */
  31.  
  32. struct bootstuff {
  33.     long        unknown;
  34.     startp_t    *bootptr;
  35. };
  36. extern struct bootstuff BootTmp8 : 0xb36;
  37.     
  38. typedef unsigned long u_long;
  39.  
  40. #define COPYPS(s,d)    BlockMove (s, d, (Size)(((s)[0]) + 1))    /* copy pas. str */
  41. #define    ZERO(s)        memset ((char *)&(s), 0, sizeof (s))    /* zero struct */
  42.  
  43. /*
  44.  * Prototypes
  45.  */
  46. static OSErr doFudge (Str31,int);
  47. static OSErr findAppl (Str31);
  48. static OSErr getPrefs (Str31, long, StringHandle *, Str31, Str31, Str31, Str31, Str31, Str31);
  49. static OSErr getFromAppl (Str31, Str31, long *);
  50. extern void main (Handle);
  51. extern void ShowINIT (Integer);
  52. static void start (void);
  53.  
  54. /*
  55.  * Globals for routines in volops.c
  56.  */
  57. Integer        BootVol;
  58. StringPtr    Clue0;
  59. Integer        ClueID;
  60. Boolean        Quit;
  61.  
  62. /*
  63.  *=========================================================================
  64.  * start () - routine given control by INIT 31
  65.  *    Must be first code in first file in project
  66.  *=========================================================================
  67.  */
  68. static
  69. void
  70. start ()
  71. {
  72.     asm
  73.     {
  74.         move.l    a0,-(sp)            /* pass handle to selves to main */
  75.         move.l    (a0),a4                /* set A4 to allow refs to globals */
  76.         jsr        main                /* call main routine */
  77.         move.l    (sp)+,a0            /* pop arg to restore stack */
  78.     }
  79. }
  80.  
  81.  
  82. extern unsigned char ApplScratch[12] : 0xa78;
  83.  
  84. /*
  85.  *=========================================================================
  86.  * main - main sequence
  87.  *=========================================================================
  88.  */
  89. void
  90. main (self)
  91.     Handle self;
  92. {
  93.     register OSErr result;
  94.     StringHandle master;            /* name of master folder on server */
  95.     Str31    applName;                /* name of RevRdist application */
  96.     Str31    prefName;                /* name of prefs file */
  97.     Str31    zoneName;                /* server zone name */
  98.     Str31    serverName;                /* name of server to use */
  99.     Str31    userName;                /* name to log on to server as */
  100.     Str31    serverVol;                /* server volume to user */
  101.     Str31    password;                /* user password on server */
  102.     Str31    startName;                /* "Set Startup" name to force */
  103.     Str255    s;                        /* string temp */
  104.     Integer    volref;                    /* dummy for GetVol */
  105.     long    RRflags;                /* RevRdist flags */
  106.     StringPtr    sp;                    /* temp */
  107.     AFPVolMountInfo mi;                /* mounting info for accessMaster */
  108.  
  109.     HLock (self);
  110.     SetResLoad (true);                /* should already be true, but ... */
  111.     result = (FSFCBLen <= 0);        /* make sure HFS */
  112.     startName[0] = 0;
  113.     RRflags = 0;
  114.     Quit = false;
  115.     /*
  116.      * Find the RevRdist application
  117.      */
  118.     if (result == 0)
  119.         result = findAppl (applName);
  120.     /*
  121.      * Get run flags and the name of the preferences file from RevRdist
  122.      */
  123.     if (result == 0)
  124.         result = getFromAppl (applName, prefName, &RRflags);
  125.     /*
  126.      * Extract the preferences & check if it's time to run
  127.      */
  128.     master = 0;
  129.     if (result == 0)
  130.         result = getPrefs (prefName, RRflags, &master,
  131.                     serverVol, zoneName, serverName, userName, password,
  132.                     startName);
  133.     /*
  134.      * Set the shell, if specified, whether we run RevRdist or not
  135.      */
  136.     if (startName[0])
  137.         (void) doFudge (startName, 0);
  138.     /*
  139.      * If RevRdist is not going to mount the server, we should try
  140.      */
  141.     if (result == 0 && (RRflags & PF_NOMOUNT))
  142.     {
  143.         GetVol (s, &BootVol);
  144.         COPYPS (*master, s);
  145.         ZERO(mi);
  146.         mi.length = sizeof(mi);
  147.         mi.media = AppleShareMediaType;
  148.         sp = (StringPtr)mi.AFPData;
  149.         if (zoneName[0] == 0)
  150.         {
  151.             zoneName[1] = '*';        /* supply default zone name */
  152.             zoneName[0] = 1;
  153.         }
  154.  
  155. #define    COPYPREF(nn,ee) \
  156.         COPYPS(nn, sp); \
  157.         mi.ee = sp - (StringPtr)(&mi); \
  158.         sp += 32;
  159.  
  160.         COPYPREF(zoneName, zoneNameOffset);
  161.         COPYPREF(serverName, serverNameOffset);
  162.         COPYPREF(serverVol, volNameOffset);
  163.         COPYPREF(userName, userNameOffset);
  164.         COPYPREF(password, userPasswordOffset);
  165. #undef    COPYPREF
  166.  
  167.         result = accessMaster (s, &mi);
  168.     }
  169.     if (master)
  170.         DisposHandle ((Handle) master);
  171.     if (result == 0 && Quit == false)
  172.         result = doFudge (applName,1);
  173.     HUnlock (self);
  174. }
  175.  
  176.  
  177.  
  178. /*
  179.  *=========================================================================
  180.  * doFudge (ap,flag) - modify memory copy of boot blocks to make RevRdist
  181.  *            application the "startup" application
  182.  * entry:    ap = name of RevRdist
  183.  *            flag indicates whether ApplScratch should be munged also
  184.  * returns:    0 if all went well, 
  185.  *            <> 0 if boot blocks area looks fishy
  186.  *=========================================================================
  187.  */
  188. static
  189. OSErr
  190. doFudge (ap, flag)
  191.     Str31    ap;
  192.     int        flag;
  193. {
  194. register unsigned char c;
  195. register startp_t *    startp;            /* ptr to boot param block */
  196.     long *        lp;                    /* pts into ApplScratch */
  197.  
  198.     /*
  199.      * Locate the memory copy of the system startup information
  200.      * Check that it appears intact.
  201.      * Replace the startup program name with RevRdist name
  202.      */
  203.     startp = (startp_t *)((long)MemTop / 2);
  204.  
  205.     if (startp->startid != STARTID) {
  206.         startp = BootTmp8.bootptr;
  207.         if (startp->startid != STARTID)
  208.             return 1;
  209.     }
  210.     if (startp->azero)
  211.         return 2;
  212. #define    CHECK(w, e)    if ((c = startp->w[0]) == 0 || c > 15) return (e)
  213.     CHECK (sysname, 3);
  214.     CHECK (shellname, 4);
  215.     CHECK (debuggername, 5);
  216.     CHECK (disassmname, 6);
  217.     CHECK (startscreen, 7);
  218.     CHECK (startappl, 8);
  219.     CHECK (scrapname, 9);
  220. #undef CHECK
  221.     if (startp->fcbcnt < 0)
  222.         return 10;
  223.     if (startp->eventcnt < 0)
  224.         return 11;
  225.     COPYPS (ap, startp->startappl);
  226.     if (flag)
  227.     {
  228.         lp = (long *)(ApplScratch + 8);
  229.         lp[0] = CREATOR;            /* leave a "note" for RevRdist */
  230.     }
  231.     return 0;
  232. }
  233.  
  234.  
  235.  
  236. /*
  237.  *=========================================================================
  238.  * findAppl (ap) - locate RevRdist application and return its name
  239.  * entry:    ap = Str31 to contain name
  240.  * returns:    0 on success, else OSErr
  241.  *=========================================================================
  242.  */
  243. static
  244. OSErr
  245. findAppl (ap)
  246.     Str31 ap;
  247. {
  248.     OSErr            error;
  249.     int                i;
  250.     Str255            name;
  251.     CInfoPBRec        ci;
  252.     unsigned long    besttime;
  253.  
  254.     /*
  255.      * Search the current directory to find a file with the correct
  256.      * type (APPL) and CREATOR and the most recent mod time.
  257.      */
  258.     besttime = 0;
  259.     ZERO (ci);
  260.     ci.hFileInfo.ioNamePtr = name;
  261.     for (i = 1, error = 0; ! error; i++)
  262.     {
  263.         name[0] = 0;
  264.         ci.hFileInfo.ioDirID = 0;
  265.         ci.hFileInfo.ioFDirIndex = i;
  266.         error = PBGetCatInfo (&ci, false);
  267.         if (error == 0)
  268.         {
  269.             if (ci.hFileInfo.ioFlAttrib & 0x10)
  270.                 continue;            /* if directory */
  271.             if (ci.hFileInfo.ioFlFndrInfo.fdType == 'APPL'
  272.              && ci.hFileInfo.ioFlFndrInfo.fdCreator == CREATOR)
  273.             {
  274.                 if (name[0] > 15)
  275.                     continue;        /* ignore if unacceptable name */
  276.                 if (ci.hFileInfo.ioFlMdDat < besttime)
  277.                     continue;        /* if older than current best */
  278.                 besttime = ci.hFileInfo.ioFlMdDat;
  279.                 COPYPS (name, ap);
  280.             }
  281.         }
  282.     }
  283.     if (besttime)
  284.         error = 0;                    /* no error if any candidate found */
  285.     return error;
  286. }
  287.  
  288.  
  289.  
  290. /*
  291.  *=========================================================================
  292.  * getPrefs (pf, fl, mf, sv, zn, sn, un, pw, an) - extract info from preferences file
  293.  * entry:    pf = name of preferences file
  294.  *            fl = RevRdist run flags
  295.  *            mf = ptr to handle for master folder name string
  296.  *            sv = buf for server volume name
  297.  *            zn = buf for server zone
  298.  *            sn = buf for server name
  299.  *            un = buf for user name
  300.  *            pw = buf for password
  301.  *            an = buf for startup application
  302.  * returns:    0 if preferences found and set,
  303.  *            1 if not time to run
  304.  *            other <> 0 on error
  305.  *=========================================================================
  306.  */
  307. static
  308. OSErr
  309. getPrefs (pf, fl, mf, sv, zn, sn, un, pw, an)
  310.     Str31            pf;
  311.     long            fl;
  312.     StringHandle *    mf;
  313.     Str31            sv;
  314.     Str31            zn;
  315.     Str31            sn;
  316.     Str31            un;
  317.     Str31            pw;
  318.     Str31            an;
  319. {
  320.     Integer        curref;                /* current resource file */
  321.     OSErr        error;
  322.     Handle        h;                    /* handle to resources */
  323.     int            i;                    /* temp counter */
  324.     int            len;                /* temp string length */
  325.     u_long        interval;            /* running interval from prefs */
  326.     u_long        now;                /* current time */
  327.     Handle        ph;                    /* handle to interval resource */
  328.     Integer        refnum;                /* resource file refnum */
  329.     StringPtr    sp;                    /* ptr to resource strings */
  330.     Integer        theID;                /* dummy for GetResInfo */
  331.     ResType        theType;            /* dummy for GetResInfo */
  332.     Integer        vrefnum;            /* resource file vrefnum */
  333.     HParamBlockRec pb;                /* HFS parameter block */
  334.  
  335.     /*
  336.      * Extract the various preference resources from the preferences file
  337.      */
  338.     error = 0;
  339.     an[0] = 0;
  340.     curref = CurResFile ();
  341.     refnum = OpenRFPerm (pf, 0, fsRdWrPerm);
  342.     if (refnum == -1)
  343.         return ResError ();
  344.     /*
  345.      * Get the optional name of the startup application, whether anything
  346.      * else goes right or not
  347.      */
  348.     h = Get1Resource ('STR ', STR_START);    /* try prefs first */
  349.     if (!h)
  350.     {
  351.         UseResFile (curref);        /* then try inside ourselves */
  352.         h = Get1Resource ('STR ', STR_START);
  353.         UseResFile (refnum);
  354.     }
  355.     if (h)
  356.     {
  357.         sp = (StringPtr)(*h);
  358.         if (sp[0] < 16)
  359.             COPYPS (sp, an);
  360.         ReleaseResource (h);
  361.     }
  362.     if (!(fl & PF_TOUCH))
  363.     {
  364.         /*
  365.          * Get the interval.
  366.          * If it's not time to run yet, exit
  367.          */
  368.         ph = Get1Resource (TYPE_LONG, TIME_INTERVAL);
  369.         if (!ph)
  370.             goto resexit;
  371.         if (SizeResource (ph) < sizeof (interval))
  372.         {
  373.             error = resNotFound;
  374.             goto exit;
  375.         }
  376.         interval = *(u_long *)(*ph);
  377.         GetDateTime (&now);
  378.         error = GetVRefNum (refnum, &vrefnum);
  379.         if (error)
  380.             goto exit;
  381.         ZERO (pb);
  382.         pb.fileParam.ioNamePtr = pf;
  383.         pb.fileParam.ioVRefNum = vrefnum;
  384.         error = PBHGetFInfo (&pb, false);
  385.         if (error)
  386.             goto exit;
  387.         if ((u_long) pb.fileParam.ioFlMdDat + interval > now)
  388.         {
  389.             error = 1;                /* not time yet */
  390.             goto exit;
  391.         }
  392.     }
  393.     /*
  394.      * Go ahead and extract the remaining preference strings
  395.      */
  396.     h = Get1Resource ('STR ', STR_MASTF);
  397.     if (!h)
  398.         goto resexit;
  399.     /*
  400.      * The master folder STR is a complete path.
  401.      * We also want the first component.
  402.      */
  403.     sp = (StringPtr)(*h);
  404.     len = sp[0];
  405.     if (len > 32)
  406.         len = 32;
  407.     for (i = 1; i < len; i++)
  408.         if (sp[i] == ':')
  409.             break;
  410.         else
  411.             sv[i] = sp[i];
  412.     if (i > 31)
  413.         goto badstring;
  414.     sv[0] = i - 1;    
  415.     *mf = (StringHandle) h;
  416.     DetachResource(h);
  417.  
  418.     h = Get1Resource ('STR ', STR_ZONE);
  419.     if (h)                        /* zone is optional */
  420.     {
  421.         sp = (StringPtr)(*h);
  422.         if (sp[0] > 31)
  423.             goto badstring;
  424.         COPYPS (sp, zn);
  425.         ReleaseResource (h);
  426.     }
  427.     else
  428.         zn[0] = 0;
  429.  
  430.     h = Get1Resource ('STR ', STR_SRVR);
  431.     if (!h)
  432.         goto resexit;
  433.     sp = (StringPtr)(*h);
  434.     if (sp[0] > 31)
  435.         goto badstring;
  436.     COPYPS (sp, sn);
  437.     ReleaseResource (h);
  438.  
  439.     h = Get1Resource ('STR ', STR_USER);
  440.     if (h)                        /* user is optional */
  441.     {
  442.         sp = (StringPtr)(*h);
  443.         if (sp[0] > 31)
  444.             goto badstring;
  445.         COPYPS (sp, un);
  446.         ReleaseResource (h);
  447.     }
  448.     else
  449.         un[0] = 0;
  450.  
  451.     h = Get1Resource ('STR ', STR_PASS);
  452.     if (h)                        /* password is optional */
  453.     {
  454.         sp = (StringPtr)(*h);
  455.         if (sp[0] > 31)
  456.             goto badstring;
  457.         COPYPS (sp, pw);
  458.         ReleaseResource (h);
  459.     }
  460.     else
  461.         pw[0] = 0;
  462.     if (!(fl & PF_TOUCH))
  463.     {
  464.         /*
  465.          * "Change" a resource to update the mod time so we don't
  466.          * get in a boot/run/reboot loop
  467.          */
  468.         ChangedResource (ph);
  469.         WriteResource (ph);
  470.     }
  471.     goto exit;
  472.  
  473. resexit:
  474.     error = ResError ();
  475.     if (!error)
  476.         error = resNotFound;
  477.     goto exit;
  478.  
  479. badstring:
  480.     ReleaseResource (h);
  481.     error = bdNamErr;
  482.  
  483. exit:
  484.     if (ph)
  485.         ReleaseResource (ph);
  486.     if (refnum != curref)
  487.     {
  488.         (void) CloseResFile (refnum);
  489.         (void) UseResFile (curref);
  490.     }
  491.     return error;
  492. }
  493.  
  494.  
  495.  
  496.  
  497. /*
  498.  *=========================================================================
  499.  * getFromAppl (ap, pf, fl) - extract flags and preferences file name from appl file
  500.  * entry:    ap = name of RevRdist application in current directory
  501.  *            pf = buf for prefs file name
  502.  *            fl = ptr to flags long word
  503.  * returns    0 if pf set,
  504.  *            <> 0 on error
  505.  *=========================================================================
  506.  */
  507. static
  508. OSErr
  509. getFromAppl (ap, pf, fl)
  510.     Str31        ap;
  511.     Str31        pf;
  512.     long        *fl;
  513. {
  514.     Integer        curref;                /* current resource file */
  515.     OSErr        error;
  516.     Handle        h;
  517.     Integer        refnum;                /* resource file refnum */
  518.     StringPtr    sp;
  519.  
  520.     /*
  521.      * We just extract the STR_PREFS resource from the RevRdist
  522.      * application to get the name of its default preferences file.
  523.      */
  524.     error = 0;
  525.     curref = CurResFile ();
  526.     refnum = OpenRFPerm (ap, 0, fsRdPerm);
  527.     if (refnum == -1)
  528.         return (ResError ());
  529.     h = Get1Resource ('STR ', STR_PREFS);
  530.     if (h)
  531.     {
  532.         sp = (StringPtr)(*h);
  533.         if (sp[0] < 32)
  534.         {
  535.             COPYPS (sp, pf);
  536.             ShowINIT (RSRC_INITICON);
  537.         }
  538.         else
  539.             error = bdNamErr;
  540.         ReleaseResource (h);
  541.     }
  542.     else
  543.         error = ResError ();
  544.     if (error == 0)
  545.     {
  546.         h = Get1Resource ('Long', FLAG_PARM);
  547.         if (h)
  548.         {
  549.             if (SizeResource(h) == sizeof(*fl))
  550.                 BlockMove (*h, (Ptr)fl, sizeof (*fl));
  551.             ReleaseResource (h);
  552.         }
  553.     }
  554.     if (refnum != curref)
  555.     {
  556.         (void) CloseResFile (refnum);
  557.         (void) UseResFile (curref);
  558.     }
  559.     return error;
  560. }
  561.  
  562. /*
  563.  * dummy panic routine
  564.  */
  565. void
  566. panic (Boolean f, enum error_e id, StringPtr sp, ...)
  567. {
  568.     Quit = true;
  569. }